﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace USARTHelper
{
    public partial class ui_window : Form
    {
        public ui_window()
        {
            InitializeComponent();
        }

        int byteCount = 0;
        string lastline = "";

        int rCount = 0;
        int rCmdCount = 0;
        int tCount = 0;
        bool isRecving = false;
        bool toClose = false;
        Color oColor = Color.White;

        private void Window_Load(object sender, EventArgs e)
        {
            comboBox1.SelectedIndex = 0;
            comboBox2.SelectedIndex = 6;
            comboBox3.SelectedIndex = 0;
            comboBox4.SelectedIndex = 3;
            comboBox5.SelectedIndex = 0;

            ui_consolehex.BackColor = ui_consolestr.BackColor = Color.LightGray;
            //ui_terminal.Font = new Font("Fixedsys", 12, GraphicsUnit.Pixel);
        }

        private delegate void OutputDelegate(string text);
        private void appendHex(string text)
        {
            if (this.InvokeRequired)
            {
                OutputDelegate outputdelegate = new OutputDelegate(appendHex);
                Invoke(outputdelegate, text);
            }
            else
            {
                if (text == "&清屏")
                {
                    ui_consolehex.Text = "";
                }
                else
                {
                    ui_consolehex.AppendText(text);
                }
                //if (console.TextLength < 900 || auto_clean_console.Checked == false)
                //{
                //    console.AppendText(text);

                //    console.SelectionStart = console.Text.Length;
                //    console.Focus();
                //    command.Focus();
                //}
                //else
                //{
                //    console.Text = "";
                //}
            }
        }
        private void appendStr(string text)
        {
            if (this.InvokeRequired)
            {
                OutputDelegate outputdelegate = new OutputDelegate(appendStr);
                Invoke(outputdelegate, text);
            }
            else
            {
                if (text == "&清屏")
                {
                    ui_consolestr.Text = "";
                }
                else
                {
                    ui_consolestr.AppendText(text);
                }
            }
        }
        private void appendCon(string text)
        {
            if (this.InvokeRequired)
            {
                OutputDelegate outputdelegate = new OutputDelegate(appendCon);
                Invoke(outputdelegate, text);
            }
            else
            {
                if (text == "&清屏")
                {
                    ui_console.AppendText("\n");
                    ui_console.AppendText("[" + textBox1.Text + "]\n");
                }
                else
                {
                    ui_console.AppendText(text);

                }
            }
        }
        private void scroll2end(string text)
        {
            if (this.InvokeRequired)
            {
                OutputDelegate outputdelegate = new OutputDelegate(scroll2end);
                Invoke(outputdelegate, text);
            }
            else
            {
                scroll2end();
            }
        }
        void console_nextline()
        {
            appendCon("\n");
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            timer1.Enabled = true;
            isRecving = true;
            int count = serialPort1.BytesToRead;
            //rCount += count;

            //if (isShowString)
            //{
            //    //string input = serialPort1.ReadExisting();
            //    //appendHex(input);
            //    byte[] buff = new byte[count];
            //    int readcount = serialPort1.Read(buff, 0, count);

            //    for (int i = 0; i < count; i++)
            //    {
            //        rCount++;

            //        lastline += buff[i].ToString("X2") + " ";
            //        if (textBox1.Text != string.Empty)
            //        {
            //            if (lastline.Contains(textBox1.Text.ToUpper()))
            //            {
            //                byteCount = 0;
            //                appendStr("&清屏");
            //                lastline = "";
            //                continue;
            //            }
            //        }
            //        appendStr(Encoding.ASCII.GetString(buff, i, 1));

            //        byteCount++;
            //    }

            //    if (readcount != count)
            //    {
            //        MessageBox.Show("读取数据量与缓冲区内数据量不一致！");
            //    }
            //}
            //else
                byte[] buff = new byte[count];
                int readcount = serialPort1.Read(buff, 0, count);

                //appendHex(" ");
                //appendStr("|");

                for (int i = 0; i < count; i++)
                {
                    if (serialPort1.IsOpen == false)
                    {
                        return;
                    }          
                    
                    if (toClose)
                    {
                        break;
                    }
                    if (toExit)
                    {
                        break;
                    }

                    rCount++;

                    lastline += buff[i].ToString("X2") + " ";
                    if (textBox1.Text != string.Empty)
                    {
                        if (lastline.Contains(textBox1.Text.ToUpper()))
                        {
                            byteCount = 0;
                            appendHex("&清屏");
                            appendStr("&清屏");
                            appendCon("&清屏");
                            string[] tmpStr = lastline.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                            rCount -= tmpStr.Length;
                            rCmdCount += tmpStr.Length;
                            lastline = "";
                            continue;
                        }
                    }
                    if (byteCount % 8 == 0)
                    {
                        appendHex(" ");
                        appendStr(" ");
                    }                 
                    if (byteCount > 0)
                    {
                        if (byteCount % 16 == 0)
                        {
                            appendHex("\n ");
                            appendStr("\n ");
                            lastline = "";
                            scroll2end("");
                        }
                    }

                    appendHex(buff[i].ToString("X2"));
                    string str = "";
                    if (buff[i] > 31 && buff[i] < 127)
                    {
                        str += Encoding.ASCII.GetString(buff, i, 1);
                    }
                    else
                    {
                        str += "*";
                    }
                    appendStr(str);
                    if (buff[i] == 0xa)
                    {
                        console_nextline();
                    }
                    else
                    {
                        appendCon(str);
                    }
                    if ((byteCount + 1) % 16 > 0)
                    {
                        appendHex(" ");
                        //appendStr(" ");
                    }

                    byteCount++;
                }

                if (readcount != count)
                {
                    MessageBox.Show("读取数据量与缓冲区内数据量不一致！");
                }
                isRecving = false;
                timer1.Enabled = false;
        }

        void disable_change()
        {
            comboBox1.Enabled = false;
            comboBox2.Enabled = false;
            comboBox3.Enabled = false;
            comboBox4.Enabled = false;
            comboBox5.Enabled = false;
        }

        void enable_change()
        {
            comboBox1.Enabled = true;
            comboBox2.Enabled = true;
            comboBox3.Enabled = true;
            comboBox4.Enabled = true;
            comboBox5.Enabled = true;
        }

        private void ui_conn_Click(object sender, EventArgs e)
        {
            try
            {
                if (ui_conn.Text == "打开")
                {
                    serialPort1.PortName = comboBox1.Text;
                    serialPort1.BaudRate = int.Parse(comboBox2.Text);
                    serialPort1.Parity = (System.IO.Ports.Parity)(comboBox3.SelectedIndex);
                    serialPort1.DataBits = int.Parse(comboBox4.Text);
                    serialPort1.StopBits = (System.IO.Ports.StopBits)(comboBox5.SelectedIndex + 1);

                    serialPort1.Open();
                    ui_conn.Text = "关闭";
                    disable_change();
                    ui_consolehex.BackColor = ui_consolestr.BackColor = oColor;
                }
                else
                {
                    close();
                    ui_consolehex.BackColor = ui_consolestr.BackColor = Color.LightGray;

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        void close()
        {
            if (isRecving)
            {
                toClose = true;
                return;
            }
            serialPort1.DiscardInBuffer();
            serialPort1.DiscardOutBuffer();
            serialPort1.Close();
            ui_conn.Text = "打开";
            enable_change();
            toClose = false;
        }

        private void ui_cls_Click(object sender, EventArgs e)
        {
            byteCount = 0;
            ui_console.Text = ui_consolestr.Text = ui_consolehex.Text = "";
        }

        private void splitContainer1_Resize(object sender, EventArgs e)
        {
            //ui_consolehex.Width = splitContainer1.Panel2.Width / 2;
            ui_consolehex.Height = splitContainer1.Panel2.Height;

            //ui_consolestr.Location = new Point(ui_consolehex.Width + 1, 0);
            //ui_consolestr.Width = splitContainer1.Panel2.Width - 1 - ui_consolehex.Width;
            ui_consolestr.Height = ui_consolehex.Height;

            ui_console.Height = ui_consolestr.Height;
            ui_console.Width = splitContainer1.Width - 120 - 1 - 1 - ui_consolehex.Width - 1 - ui_consolestr.Width;

        }
        private void Window_Resize(object sender, EventArgs e)
        {
            splitContainer1.Width = this.Width - 34;
            splitContainer1.Height = this.Height - 56;
            splitContainer1.SplitterDistance = 120;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            ui_rcount.Text = " " + rCount + " + " + rCmdCount + "(命令)";
            ui_tcount.Text = " " + tCount;
            //ui_rCmdcount.Text = " " + rCmdCount;
            if (toClose)
            {
                close();
            }
            if (toExit)
            {
                if (!isRecving)
                {
                    Close();
                }
            }

        }

        void scroll2end()
        {
            ui_consolehex.ScrollToCaret();
            ui_consolestr.ScrollToCaret();
            ui_console.ScrollToCaret();
        }

        private void 更改背景颜色ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.ColorDialog cd = new ColorDialog();
            bool redo = false;
            do
            {
                if (cd.ShowDialog() == DialogResult.OK)
                {
                    Color color = cd.Color;
                    if (color == ui_consolehex.BackColor)
                    {
                        redo = true;
                        MessageBox.Show("文字颜色与背景颜色不能相同，否则会看不见文字。");
                    }
                    else
                    {
                        redo = false;

                        ui_console.BackColor=ui_consolestr.BackColor = ui_consolehex.BackColor = color;
                        oColor = color;
                    }
                }
            } while (redo);
        }

        private void 更改文字颜色ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.ColorDialog cd = new ColorDialog();
            bool redo = false;
            do
            {
                if (cd.ShowDialog() == DialogResult.OK)
                {
                    Color color = cd.Color;
                    if (color == ui_consolehex.BackColor)
                    {
                        redo = true;
                        MessageBox.Show("文字颜色与背景颜色不能相同，否则会看不见文字。");
                    }
                    else
                    {
                        redo = false;
                        ui_console.ForeColor= ui_consolestr.ForeColor = ui_consolehex.ForeColor = color;
                    }
                }
            } while (redo);
        }

        private void ui_consolehex_Enter(object sender, EventArgs e)
        {
            ui_console.Focus();
        }

        private void ui_consolestr_Enter(object sender, EventArgs e)
        {
            ui_console.Focus();
        }

        private void ui_console_Enter(object sender, EventArgs e)
        {
            if (isRecving)
            {
                return;
            }
            ui_console.SelectionStart = ui_console.Text.Length;
        }


        private void ui_console_MouseMove(object sender, MouseEventArgs e)
        {
            ui_console.SelectionStart = ui_console.Text.Length;
        }

        private void ui_console_MouseDown(object sender, MouseEventArgs e)
        {
            ui_console.SelectionStart = ui_console.Text.Length;
        }

        private void ui_console_KeyDown(object sender, KeyEventArgs e)
        {
            if (!serialPort1.IsOpen)
            {
                return;
            }

            if (e.KeyCode == Keys.Enter)
            {
                string[] strs = ui_console.Text.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                string cmd="";
                if (strs.Length > 0)
                {
                    cmd = strs[strs.Length - 1];
                }

                serialPort1.Write(cmd);
            }
        }
        bool toExit = false;
        protected override void WndProc(ref Message m)
        {
            const int WM_SYSCOMMAND = 0x0112;
            const int SC_CLOSE = 0xF060;
            if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
            {
                if (isRecving)
                {
                    toExit = true;
                    return;
                }
                Close();
            }
            base.WndProc(ref m);
        }
    }
}
